//***********************************************************************************
// Controller that decides which grid each level fallsin

// Author: Aravindh U095232L

//***********************************************************************************

function controller()
{

    level_1 = map.getCurrentGrids();
    level_2 = map.getAdjcentGrids();
    conv_type = 0;
    var count =0;


    //Level 3 grid allocator
    for(var i=0;i<10;i++)
        for(var j=0;j<10;j++)
    {   
        var curr_grid = map.getGridById(i,j);
        if( in1_in2(curr_grid) == false )
        {   
            curr_grid.prev_level = curr_grid.curr_level;
            curr_grid.curr_level = 3;
            count++;
        }
        
        if(curr_grid.prev_level==2 && curr_grid.curr_level ==3)
        {
            level_3_compress(curr_grid);
        }
        else if(curr_grid.prev_level==3 && curr_grid.curr_level ==3 && curr_grid.semaphore==0)
        {
            curr_grid.removeAllNPCs();
            curr_grid.semaphore = 1;
            curr_grid.refresh_timer=0;
        }

    }   

    //Level 1 grid allocator
    for(var i =0; i<level_1.length; i++)
    {   
        level_1[i].semaphore = 0; 
        level_1[i].prev_level = level_1[i].curr_level ;
        level_1[i].curr_level = 1;
        level_1[i].rendered_2 = false;
        level_1[i].rendered_1 = true;
        level_1[i].refresh_timer=0;
    }

    //Level 2 grid allocator
    for(var i =0; i<level_2.length; i++)
    {
        level_2[i].prev_level = level_2[i].curr_level ;
        level_2[i].curr_level = 2;
        level_2[i].semaphore = 0; 

        if(level_2[i].prev_level == 1 && level_2[i].curr_level == 2)
        {
            level_2[i].curr_level = 1.5;
            level_temp.push(level_2[i]);
            level_2[i].init_timer = global_timer;
            level_2.splice(i,1);
        }
    }

    //Level temp grid allocator
    for(var i =0;i<level_temp.length; i++)
    {
        level_temp[i].semaphore = 0; 
        level_temp[i].refresh_timer=0;
        if(moved_level_2(level_temp[i]))
            level_temp.splice(i,1);
        else if(global_timer - level_temp[i].init_timer > 350)
        {
            level_2.push(level_temp[i]);
            level_temp.splice(i,1);
        }
    }

    //Level rules polled
    if(global_timer%1000==0)
        level_3_rules();

    level_2_rules();

    level_1_rules();

}

//Function to decide whether grid is in level 1 or level2
function in1_in2(grid)
{   
    for(var i =0;i<level_1.length;i++)
        if(grid==level_1[i])
            return true;

    for(var j =0;j<level_2.length;j++)
        if(grid==level_2[j])
            return true;

    for(var k=0;k<level_temp.length;k++)
        if(grid==level_temp[k])
            return true;

    return false;
}


//Function to check if NPC is currently in corner grid
function is_corner_grid(pos)
{
    if(pos.x==0)
        return 1;
    else if(pos.x==9)
        return 2;
    else if (pos.y==0)
        return 1;
    else if (pos.y==9)
        return 2;
}

//Function to move to trigger NPC-NPC interactions
function move_to(curr_grid, obj1,obj2,index,end,obs)
{
    if (!obj1 || !obj2) {
        return;
    }

    if(obj1.reachDestination()==false)
    {    obj1.walkTo(index.colIndex, index.rowIndex, end.x, end.y,obs,index.colIndex, index.rowIndex); console.log("here");
         if(checker(obj1,obj2))
            obj1.setreachDestination(true);
    }
    else if(obj1.reachDestination()==true && obj1.start_event==false)
    {   
        corrector(obj1,obj2,obs);
        obj2.changeFacing(check_dir_npc(obj2,obj1));
        obj1.changeFacing(check_dir_npc(obj1,obj2));
        arrayOfSurroundingObjects = curr_grid;
        Interactions.determineTypeOfEvent(obj1,obj2);
        obj1.start_event=true;
    }
    else
    {
        obj1.finished =1;
    }
}

//Function to check if obj1 and obj2 are next to each other
function checker(obj1,obj2)
{
   var pos1 = obj1.getPosition();
    var pos2 = obj2.getPosition();
    if( (pos1.x==pos2.x ) && ( (pos1.y==(pos2.y+1)) || (pos1.y==(pos2.y-1)) ) )
        return true;
    else if( (pos1.y==pos2.y ) && ( (pos1.x==(pos2.x+1)) || (pos1.x==(pos2.x-1)) ) )
        return true;
    
    return false;
}

//Function to correctobj1 and obj2 so that they are next to each other
function corrector(obj1,obj2,obs)
{
    var pos1 = obj1.getPosition();
    var pos2 = obj2.getPosition();

    if(checker(obj1,obj2))
        return;

    if(pos1.y<pos2.y)
     {   if(obs[pos2.y-1][pos2.x]!=1)
           { obj1.setPosition((pos2.x),(pos2.y-1));
        return;} 
    }
     else if (pos1.y>pos2.y)
     {
        if(obs[pos2.y+1][pos2.x]!=1)
         {   obj1.setPosition((pos2.x),(pos2.y+1) );
            return;}
     }      


      if(pos1.x<pos2.x)
     {   if(obs[pos2.y][pos2.x-1]!=1)
          {  obj1.setPosition((pos2.x-1),pos2.y);
        return;}
    }
     else if (pos1.x>pos2.x)
     {
        if(obs[pos2.y][pos2.x+1]!=1)
         {   obj1.setPosition((pos2.x+1),pos1.y);
        return;}
     }      
}

//Function to create new NPC
function create(curr_grid, type_npc)
{
    eval ("aiplayer = new "+type_npc +"()");
    var obstacle_map = curr_grid.getObstacleMap();
    do{
        pos_x = Math.round(Math.random()*9);
        pos_y = Math.round(Math.random()*9);
    }while(obstacle_map[pos_y][pos_x]==1 || obstacle_map[pos_y][pos_x]==2 );

    //console.log(pos_x,pos_y);

    var obj =  {x : pos_x,
        y : pos_y,
        type :type_npc ,
        grid: curr_grid
    };
    aiplayer.init(obj);

    curr_grid.addNPC(aiplayer);
}


//Function to NPC inside building
function create_building(curr_grid, type_npc)
{
    var building = curr_grid.getBuildings()[0].obj;
    //    console.log(curr_grid.getBuildings()[0].obj);

    eval ("aiplayer = new "+type_npc +"()");
    var obstacle_map = building.getObstacleMap();
    //console.log(obstacle_map[1]);
    do{
        pos_x = Math.round(Math.random()*9);
        pos_y = Math.round(Math.random()*9);
    }while(obstacle_map[pos_y][pos_x]==1 || obstacle_map[pos_y][pos_x]==2 );
    //console.log(pos_x,pos_y);
    var object = {      x: pos_x,
        y: pos_y,
        type : type_npc,
        grid : building
    };
    aiplayer.init(object);
    aiplayer.setBuilding(building)
    aiplayer.setInsideBuilding(true);
    building.addNPC(aiplayer);
}

//Function to check if object is in second level
function in_second_level(object)
{
    var count1=0,count2 = 0;
    for(var j =0; j< level_1.length ;j++)
    {
        count1++;
    }

    for(var j =0; j< level_2.length ;j++)
    {
        count2++;
    }
    console.log("level "+ count1, count2);
    if ( (count1 == 1 && (count2== 8||count2==5) ) || (count1==2 && (count2 ==10||count2==6) ) || (count1==4 && (count2==12||count2==8) ) )
    {console.log("a");	return false;}
    return true;
}

//Function to check if object has moved to level_2
function moved_level_2(object)
{
    for(var j=0; j<level_2.length;j++)
    {
        if(object==level_2[j])
            return true;
    }

    return false;
}

//Function to check relative directions of NPCs for orientation correction
function check_dir(object1,object2)
{
    var ob1 = object1.getPosition();
    var ob2 = object2.getPosition();

    if(ob1.x==ob2.x)
    {   if(ob1.y==(ob2.y-1))
    {
        if(object2.get_facing()=="Up")
        {    conv_type = object1.getType();
             conv_object = object1;   
        }
        return "down";
    }
    else if((ob1.y-1)==ob2.y)
    {
        if(object2.get_facing()=="Down")
        {    conv_type = object1.getType();
             conv_object = object1;
        } 
        return "up";
    }
    }

    if(ob1.y==ob2.y)
    {   if(ob1.x==(ob2.x-1))
    {
        if(object2.get_facing()=="Left")
        {
            conv_type = object1.getType();
            conv_object = object1;    
        }
        return "right";
    }
    else if((ob1.x-1) == ob2.x)
    {   if(object2.get_facing()=="Right")
        {
        conv_type = object1.getType();
        conv_object = object1;
        }
        return "left";
    }
    }
}

//Function to correct direction automatically so that object1 and object 2 face each other
function check_dir_npc(object1,object2)
{
    var ob1 = object1.getPosition();
    var ob2 = object2.getPosition();

    if(ob1.x==ob2.x)
    {   if(ob1.y==(ob2.y-1))
    {
        return "down";
    }
    else if((ob1.y-1)==ob2.y)
    {
        return "up";
    }
    }

    if(ob1.y==ob2.y)
    {   if(ob1.x==(ob2.x-1))
    {
        return "right";
    }
    else if((ob1.x-1) == ob2.x)
    {
        return "left";
    }
    }
    //console.log(object1,object2);
    return object1.get_facing();    
}

//Find obstacle less pos around NOC
function find_correct_pos(curr_grid,obj)
{
    console.log(curr_grid, pos);
    var obstacle_map = curr_grid.getObstacleMap();
    var pos = obj.getPosition();

    var pos_x,pos_y;



    if(is_corner_grid(pos)==1)
        return {x:pos.x+1,y:pos.y};
    else if (is_corner_grid(pos)==2)
        return {x:pos.x-1,y:pos.y};

    switch(Math.round(Math.random()*3+1))
    {

        case 1:
            if(obstacle_map[pos.y-1][pos.x]!=1 && obstacle_map[pos.y-1][pos.x]!=2 )
                return {x:pos.x, y:pos.y-1};
            else if (obstacle_map[pos.y+1][pos.x]!=1 && obstacle_map[pos.y+1][pos.x]!=2 )
                return {x:pos.x, y:pos.y+1};
            else if (obstacle_map[pos.y][pos.x-1]!=1 && obstacle_map[pos.y][pos.x-1]!=2 )
                return {x:pos.x-1, y:pos.y};
            else if (obstacle_map[pos.y][pos.x+1]!=1 && obstacle_map[pos.y][pos.x+1]!=2 )
                return {x:pos.x+1, y:pos.y};
            break;

        case 2:
            if (obstacle_map[pos.y+1][pos.x]!=1 && obstacle_map[pos.y+1][pos.x]!=2 )
                return {x:pos.x, y:pos.y+1};
            else if (obstacle_map[pos.y][pos.x-1]!=1 && obstacle_map[pos.y][pos.x-1]!=2 )
                return {x:pos.x-1, y:pos.y};
            else if (obstacle_map[pos.y][pos.x+1]!=1 && obstacle_map[pos.y][pos.x+1]!=2 )
                return {x:pos.x+1, y:pos.y};
            else if(obstacle_map[pos.y-1][pos.x]!=1 && obstacle_map[pos.y-1][pos.x]!=2 )
                return {x:pos.x, y:pos.y-1};
            break;

        case 3:
            if (obstacle_map[pos.y][pos.x-1]!=1 && obstacle_map[pos.y][pos.x-1]!=2 )
                return {x:pos.x-1, y:pos.y};
            else if (obstacle_map[pos.y][pos.x+1]!=1 && obstacle_map[pos.y][pos.x+1]!=2 )
                return {x:pos.x+1, y:pos.y};
            else if(obstacle_map[pos.y-1][pos.x]!=1 && obstacle_map[pos.y-1][pos.x]!=2 )
                return {x:pos.x, y:pos.y-1};
            else if (obstacle_map[pos.y+1][pos.x]!=1 && obstacle_map[pos.y+1][pos.x]!=2 )
                return {x:pos.x, y:pos.y+1};
            break;

        case 4:
            if (obstacle_map[pos.y][pos.x+1]!=1 && obstacle_map[pos.y][pos.x+1]!=2 )
                return {x:pos.x+1, y:pos.y};
            else if(obstacle_map[pos.y-1][pos.x]!=1 && obstacle_map[pos.y-1][pos.x]!=2 )
                return {x:pos.x, y:pos.y-1};
            else if (obstacle_map[pos.y+1][pos.x]!=1 && obstacle_map[pos.y+1][pos.x]!=2 )
                return {x:pos.x, y:pos.y+1};
            else if (obstacle_map[pos.y][pos.x-1]!=1 && obstacle_map[pos.y][pos.x-1]!=2 )
                return {x:pos.x-1, y:pos.y};
            break;
    }
}

